Using InheritedWidget topic

Inherit The State

The InheritedWidget is fundamental to supplying efficient performance. Although Flutter has made great strides in being as efficient as possible, it's declarative approach will, in most cases, rebuild the whole screen whereas an InheritedWidget allows you to rebuild only what's changed on the screen. When it comes down to it, the less that's rebuilt, the better the performance. The more immutable (less mutable) your app, the faster it is.

Contents
Build Change Spontaneous Rebuilds The Root of Inheritance Notify of Change Control Events Time to Initialise Pause for Time

The 'Home!' example app is demonstrated in the video on your the right. With every press of the button, indeed the whole screen is rebuilt. This is just like the traditional Counter app that's created with every new Flutter project. The build() function for the _HomePageState class is called again and again with every tap. However, in this example app, the items displayed in red are updated independently of the whole screen rebuilds. They are updated only when changed leaving the rest of the screen untouched (highlighted in second screenshot).

Build Change

The series of greetings, for example, change with every five taps of the button. Only that area of the screen changes. Further, as the count increments, you'll notice the red counter also increments to keep up with the current count. It then starts over when the current count is reached. Stop pressing the button, and the red counter continues the loop. Again, only that region of the screen is updated. The rest of the screen is left unchanged. Very efficient! There is no 'rebuilding of the whole screen.' The less the interface is changed at any point in time, the better the performance. Updating the app's interface, in most instances, is the most 'expensive' operation.

Spontaneous Rebuilds

The first screenshot below highlights the two widgets that displays those two items in red. The widget, `timer.counter`, involves a timer incrementing up to the current count. The StatelessWidget, `SetState`, supplies a builder callback routine that's called again only if the App's 'InheritedWidget' is called again. That's because this `SetState` widget has been assigned as a 'dependent' to that InheritedWidget. This is a powerful aspect of using InheritedWidgets allowing for sporadic and spontaneous rebuilds of only parts of the interface (see: dependOnInheritedWidgetOfExactType()). The second screenshot is a closer look at the `SetState` builder passing the current greeting using the property, dataObject.
home_page.dart home_page.dart

Depend On Time

The first screenshot below highlights the timer class being instantiated and then added to the StateX object, _HomePageState. The second screenshot conveys the getter, `counter`, found in that timer class. Depending on whether the current count is an odd number or not, another `SetState` widget is utilized when incrementing the count. Otherwise, a StatelessWidget called, _TheCounter, is called to demonstrate how the App's InheritedWidget assigns a widget as a 'dependent' using the AppStateX's function, dependOnInheritedWidget().
home_page.dart counter_timer.dart

The Root of Inheritance

The _TheCounter StatelessWidget is displayed in the first screenshot below. Highlighted is the 'root' State object taking in this widget as a dependent through its context. Now, every time that InheritedWidget is called again, the build() function below is also called. Note, the timer class extends the StateXController class, and so has the rootState property with its dependOnInheritedWidget() function.

Thr second screenshot is the SetState widget. It too has the 'root' State object in its build() function calling the dependOnInheritedWidget() function. And so, when the app's InheritedWidget is called again, the builder callback routine is called again. See how that works?

counter_timer.dart state_extended.dart

Notify of Change

The screenshots below depicts how the Timer object is instantiated and set up. Note the _increment() function in the second screenshot calls the 'root' State object's notifyClients() function, and this means the app's InheritedWidget is called again as well as all its dependent widgets.
counter_timer.dart counter_timer.dart

Control Events

Adding controllers to StateX objects allows those controllers to react appropriately when the app is placed in the background, for example, or when the app is terminated. It is especially important in this "Hello!" example app as a Timer is involved in the operation. Such a timer would continuously run even when its not necessary. For example, this Flutter app can easily be found running on a mobile phone. With that, such an app can routinely be interrupted by the user switching to another app, answering a phone call for example, and then return to the app.

The StateX class has some twenty-six (26) event handling functions available to you to take into account the many external events that can affect your running app. In the case of the "Hello!" example app, there is a ready means to stop the Timer when the app is placed in th background as well as start the Timer up again when the user returns and the app resumes its operations (see right). This is great news since Timers and operations like it simply take up resources, and if you don't do anything about it in the first place, your app will soon be labeled a 'memory hog.'

Time to Initialise

In the screenshots below, we have the screenshot again of the Timer class being instantiated and then added to the StateX object, _HomePageState. Adding that controller now means, when the State object's initState() function is called, the initState() function in the controller, CounterTimer, is also called. Every controller added to the StateX object will have its initState() function called.

The second screenshot is that of the CounterTimer class. You can see it's in its initState() where the Timer is first initialised with the initTimer() function. It's there where the Timer begins keeping tabs on the current count. When that count increments, the Timer will keep in-step.

home_page.dart counter_timer.dart

Pause for Time

Now in the screenshots below, you see how the timer is stopped and started again depending on the circumstance. A controller class is provided an assortment of functions to address particular events. As you can readily see in the first screenshot below of the CounterTimer class, when the running app is placed in the background, for example, the pausedLifecycleState() function is called. There, the Timer is turned off. When the app is returned focus, the resumedLifecycleState() function is called and the Timer is turned on again.

The second screenshot displays the didChangeAppLifecycleState() function in the StateX class. As you see, the didChangeAppLifecycleState() functions of any and all the controllers it may contain are also called. Next, however, functions dedicated to specific cycle events are then called. You can see where the pausedLifecycleState() function and the resumedLifecycleState() function are situated.

counter_timer.dart state_extended.dart

Mixins

InheritedWidgetStateMixin StateX class Using InheritedWidget
Supplies an InheritedWidget to a State class